/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package towerdefence.model;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import net.phys2d.raw.Body;
import net.phys2d.raw.StaticBody;
import net.phys2d.raw.World;
import towerdefence.model.level.Level;

/**
 *
 * @author Gussoh
 */
public class Model {

    private static int NUM_ITERATIONS_PER_STEP = 1;
    
    private World world;
    private SortedMap<Long, CannonBall> cannonBallTimeMap = new TreeMap<Long, CannonBall>();
    private List<Player> players = new ArrayList<Player>();
    private Level level;
    private List<Runnable> invokeLaterRunnables = new ArrayList<Runnable>();
    private List<StepListener> stepListeners = new ArrayList<StepListener>();
    
    public Model(Level level, World world) {
        this.level = level;
        this.world = world;
        for (StaticBody staticBody : level.getGroundBodies()) {
            addBody(staticBody);
        }
    }

    protected void addCannonBall(CannonBall cannonBall) {
        world.add(cannonBall);
        cannonBallTimeMap.put(System.currentTimeMillis(), cannonBall);
    }

    protected void addBody(Body b) {
        world.add(b);
    }
    
    public void doStep() {
        
        synchronized(invokeLaterRunnables) {
            for (Runnable runnable : invokeLaterRunnables) {
                runnable.run();
            }
            invokeLaterRunnables.clear();
        }
        
        for (int i = 0; i < NUM_ITERATIONS_PER_STEP; i++) {
            world.step();
        }
        
        for (StepListener stepListener : stepListeners) {
            stepListener.step();
        }
       
    }
    
    public List<Player> getPlayers() {
        return players;
    }

    void playerDied(Player player) {
        players.remove(player);
        if(players.size() < 2) {
            // TODO: GAME OVER!!!
        }
    }

    public void setPlayers(List<Player> players) {
        this.players = players;
    }

    public Level getLevel() {
        return level;
    }
    
    public void invokeLater(Runnable runnable) {
        synchronized(invokeLaterRunnables) {
            invokeLaterRunnables.add(runnable);
        }
    }
    
    public void addStepListener(StepListener s) {
        stepListeners.add(s);
    }
    
    public void removeStepListener(StepListener s) {
        stepListeners.remove(s);
    }
}
